#include "thttpd.h"
#include <sys/types.h>
#include <sys/wait.h>
#include "shmem.h"
#include "msg_queue_peer.h"

/**
 * 线程处理函数，并设置为非阻塞，自动回收线程资源
 * 参数需要传递accected的值
 * 返回值
 */
static void *msg_request(void *arg)
// 因为被static修饰，所以返回值必须是void*类型的
{
	// 这里客户端描述符通过参数传进来了 accepted
	int sock = *((int *)arg);
	// 一般情况下，线程终止后，其终止状态一直保留到其它线程调用pthread_join获取它的状态为止。
	// 但是线程也可以被置为detach状态，这样的线程一旦终止就立刻回收它占用的所有资源，而不保留终止状态。
	pthread_detach(pthread_self());
	/**
	 * 	pthread_t pthread_self(void);
		返回值：函数返回一个 pthread_t 类型的值，该值表示调用线程的线程标识符。
		参数：函数不接受任何参数。
	*/
	// 进入游离态 ,参数为该线程的县城标识符
	//  在一个进程中创建线程，默认的状态是可结合的，这时候，线程必须等待原有的进程结束后才算是线程终止，
	//  这个时候才能被回收他的资源。我们一般不关心线程的终止状态，所以一般在创建线程结束以后，就可以把线程设置成分离状态，
	//  这时候的线程不被其他线程所等待，当线程运行结束终止以后，他会自动释放自己所占用的资源。
	printf("进入线程函数\n");
	// handler_msg作为所有的请求处理入口
	return (void *)handler_msg(sock);
	// 将函数的返回值强转为void *类型的，实现线程函数返回值的统一
}

struct shm_param para; // 共享内存的首地址
int *total;			   // 指向共享内存中数据节点总个数  6  4
struct data *shmData;	   // 指向共享内存中节点缓存数组头
void *node_p;

/**
 * 这里是主函数
 * 可以用命令行参数自定义端口号
 */
int main(int argc, char *argv[])
{
	// pp =shmchar_p_creat();//创建共享内存
	printf("开始运行.............\n");
	int ret = -1;
	printf("----------------%d", __LINE__);

	ret =  shm_init(&para, "dy", 1024);
	if (ret < 0)
	{
		return -1;
	}

	node_p = shm_getaddr(&para);
	if (node_p == NULL)
	{
		return -1;
	};
	printf("创建共享内存成功！\n");
	printf("----------------%d", __LINE__);

	int port = 80;
	// 如果不传递端口，那么使用默认端口80
	// 如果命令行参数大于1，那就用命令行参数传递端口号
	if (argc > 1)
	{
		port = atoi(argv[1]); // 字符串转int
	}
	// 默认端口号是80，也可以通过命令行传参从终端输入
	// 初始化服务器
	int lis_sock = init_server(port); // 函数内写到了listen监听套接字
	// 也就是这里只传参穿了个端口号 ：80

	while (1) // 循环等待链接：链接成功后创建线程
	{
		struct sockaddr_in peer;	  // 网路信息结构体
		socklen_t len = sizeof(peer); // 求所占空间的大小
		// 这里的sock其实就相当于acceptd
		int sock = accept(lis_sock, (struct sockaddr *)&peer, &len);
		// 链接网页客户段
		if (sock < 0)
		{
			perror("accept failed");
			continue;
		}

		// 每次接收一个链接后，会自动创建一个线程，这实际上就是多线程并发服务器模型的应用
		// 从线程处理新客户端的发来的请求，主线程继续循环等待链接
		pthread_t tid;
		if (pthread_create(&tid, NULL, msg_request, (void *)&sock) > 0)
		// 调用线程处理函数 msg_request（这里提一下回调函数）
		// 函数指针，指针函数，函数指针数组
		// int* getArrayPointer(int arr[], int size)   指针函数
		// int (*funcPtr)(int, int) = add;             函数指针
		// int (*funcs[5])(void);
		// 声明一个包含5个元素的数组，每个元素都是指向函数的指针

		{
			perror("pthread_create failed");
			close(sock);
		}
	}
	return 0;
}
